iT邦幫忙

2024 iThome 鐵人賽

DAY 29
0

遺珠之憾

其實礙於篇幅,還是很多東西想講,只好大雜燴講一下。

版本管理

可能有人以為使用了 git 就是版本管理,也有人認為套件發版是一個版本,在拆分的時候才有版本管理的議題,等等原因。但我並不是這樣想,就算你不是採用微前端或是套件分包都應該要有版本管理的概念。我的觀點是:「所有的 Commit 都是獨立的版本」。

這就可以說到,我認為「只要共用就要管理版本」。共用這件事對於大部分工程師已經是再稀鬆平常的事,但隨著前端團隊的協作和專案規模的成長,「共用」帶來的卻是更大的負擔。經常我們軟體開發帶來許多問題,改 A 壞 B、套件相容、理解共用、依賴管理... 諸多問題。如果平常執行模組共用時就有明確的版本管理觀念,關注向下相容的異動設計,確保重構的影響範圍與測試
的覆蓋範圍,如此才能有效的控制共用帶來的副作用。

微前端測試

前面一直沒有提到測試,微前端的測試看似是一個很大的議題,但其實沒有想像中複雜與可怕。與大部分測試一樣,單元測試或整合測試之下,跨服務時就 Mock API 回傳的資料,這樣就可以完成測試。以邏輯上來說,Mock 微前端的 API 比起 Mock 後端 API 相對簡單很多,大部分情境是不需要設計太複雜的資料結構的。

實戰踩坑經驗

我實際在實戰上遇到最多的是 React 為主,Vue 為輔的微前端開發,在一年半左右的開發中累積各種經驗。這篇要分享我在實戰開發遇到各種費盡心思處理的坑,幫助使用的人好好避開這些雷到崩潰的道路。

當使用同一個 React instance 不能手動卸載

你如果要滿足一個完整的生命週期,你可能會遇到 Attempted to synchronously unmount a root while React was already rendering. 這個錯誤。官方的 Issue 在這,這問題是因為實際你在 React 在 Rerender 階段執行 root.unmount() 這個行為。

解決方式很簡單,你可以使用 Promise.resolve() 延遲 EventLoop 執行的時間。

已經使用 ModuleFederation shared,依然無法共享相關的程式碼

這可能有多種可能,我也不保證你會遇到跟我一樣的問題,但我列出幾個可能。

版本不一致

如果使用 MF,它會優先使用「最高版本」。也就是說,當你先載入 v1.0.0 版本,但接著卻載入 v1.0.1 版,那 MF 會把 v1.0.1 覆蓋 v1.0.0 的版本。所以確保載入時應該要一致的版本。

拆分包沒有進行 shared

以 React 來說,除了你會共享 reactreact-dom 兩個套件。但其實我們在寫 React 時是有使用分包的,這時你必須把對應版本的分包也加入到你共享的範圍。分別是 react/jsx-runtimereact-dom/client 兩個入口,對於 MF 它會認為是不同的東西。

使用了 Webpack 的 dynamic remote module 沒設定作用域

通常我們剛開始學習使用 MF 會使用 library.type=var 這個打包模式,它會直接把 container 掛載到 window 之下。比較有嘗試精神的,會嘗試處理,希望初始化不要載入那麼多資源,你可能會想用 dynamic 的方式直接使用。

const CONTAINER_NAME = "CONTAINER_NAME";
const MODULE_NAME = "./MODULE_NAME";
const container = window[CONTAINER_NAME];
const getModules = await container.get(MODULE_NAME);
const module = await getModules();

但直接這麼做會有的問題是你沒有指定作用域,所以載入後是完全不共享的。所以要程式中定義作用域,透過 webpack 在打包過程中提供的隱藏方法來取得模組。

const CONTAINER_NAME = "CONTAINER_NAME";
const MODULE_NAME = "./MODULE_NAME";
const SHARED_SCOPE = "default";
await __webpack_init_sharing__(SHARED_SCOPE);
const container = window[CONTAINER_NAME];
await container.init(__webpack_share_scopes__[SHARED_SCOPE]);
const getModules = await container.get(MODULE_NAME);
const module = await getModules();

上一篇
(二十八) 你可能不需要微前端
下一篇
(三十) 後記
系列文
前端也可以搞微服務?!前端最複雜的一種架構30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言